/**
  ETFRoot project, Anyang Normal University && IMP-CAS
  \class ETFDetectorManager
  \brief To manager the creation and registration of detectors according to the users'
  intention. It also by-the-way do the channel-mapping work.
  \author SUN Yazhou, asia.rabbit@163.com
  \since 2021-10-26
  \date 2021-11-30 last modified
  \attention
  changelog
  <table>
  <tr>  <th>Date         <th>Author      <th>Description                   </tr>
  <tr>  <td>2021-10-26   <td>Asia Sun    <td>file created                  </tr>
  </table>

  \copyright Copyright (c) 2021 Anyang Normal U. && IMP-CAS with LGPLv3 LICENSE
*/

#ifndef ETFDetectorManager_h
#define ETFDetectorManager_h

#include <vector>
#include <map>
#include <string>
#include <Rtypes.h>

using std::vector;
using std::string;
using std::map;

class TGraph;
class ETFHPTDCChannel;
class ETFAmplitudeChannel;
class ETFDetector;

class ETFDetectorManager{
public:
  static ETFDetectorManager *Instance();
  virtual ~ETFDetectorManager();

  /// identify ch as a hit and add to a specific detector
  virtual void Assign(ETFHPTDCChannel *ch);
  virtual void Assign(const ETFAmplitudeChannel *ch);
  virtual void Reset(); ///< clear the data for next event
  void SetBunchID(unsigned i){ fBunchID = i; }
  void SetEventIndex(int i){ fEventIndex = i; }
  virtual void Draw(); ///< draw the detector and highlight the hits
  virtual void Register(); ///< register all dets to main tree
  virtual void Configure(); ///< create the detectors w.r.t. config file

  const map<int, unsigned> &GetChannelMap() const{ return fChMap; }
  map<int, unsigned> &GetChannelMap(){ return fChMap; }
  unsigned GetUID(int chid) const;
  const map<string, ETFDetector *> &GetDetectorMap() const{ return fDet; }
  ETFDetector *GetDetector(const char *name) const;
  ETFDetector *GetDetector(int detId) const; ///< retrieve detector by detector id
  double GetTargetZ() const{ return fTargetZ; }
  virtual void Print(); ///< print the detector info
  unsigned GetBunchID() const;
  int GetEventIndex() const{ return fEventIndex; }
  void SetDebug(bool opt = true){ fDebug = opt; }

  ClassDef(ETFDetectorManager, 1);

protected:
  ETFDetectorManager();
  virtual void Record(ETFDetector *det, const char *name); ///< record det in map fDet and fDetName
  virtual void ConfigureDraw(); ///< draw the dipole magnet and the neutral beamline

  static ETFDetectorManager *fInstance;
  map<string, ETFDetector *> fDet; ///< map<detName, det> created detector list
  map<int, const char *> fDetName; ///< map<detId, detName>: for uid<->det mapping
  map<int, unsigned> fChMap; ///< channel id map: <chId, UID>
  double fTargetZ; ///< target z position
  unsigned fBunchID; ///< i.e. trigger time id for the current event, see ETFHPTDCChannel::GetTimeToTrig()
  int fEventIndex; ///< event index for the current event

  TGraph *fGMagnet, *fGBeamLine; //! ///< for drawing the dipole magnet and the beamline
  TGraph *fGTarget; //! ///< for drawing the target

  bool fDebug; ///< print each channel after assignment
};

#endif
